﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Caching;
using System.Xml;
using ChannelVN.Cached.Common;
using ChannelVN.Cached.Config;

namespace ChannelVN.Cached.UrlRewrite
{
    public class _301Redirection
    {
        #region Config file object
        private List<RedirectRule> RedirectRules;
        public struct RedirectRule
        {
            public RedirectRule(string url, string parameters, string method)
            {
                this.Url = url;
                this.Parameters = parameters;
                this.Method = method;
            }
            public string Url, Parameters, Method;
        }

        public _301Redirection()
        {
            string cacheName = "Cache_OldUrlRedirectionRules";
            RedirectRules = HttpContext.Current.Cache[cacheName] as List<RedirectRule>;
            if (null == RedirectRules)
            {
                RedirectRules = new List<RedirectRule>();

                try
                {
                    string configFilePath = HttpContext.Current.Server.MapPath("/Config/OldRewriteRules.config");
                    XmlDocument xmlDoc = new XmlDocument();
                    xmlDoc.Load(configFilePath);

                    XmlNodeList nlstRules = xmlDoc.DocumentElement.SelectNodes("//rules/rule");

                    for (int i = 0; i < nlstRules.Count; i++)
                    {
                        RedirectRule rule = new RedirectRule();
                        rule.Url = nlstRules[i].SelectSingleNode("url").InnerText;
                        rule.Parameters = nlstRules[i].SelectSingleNode("params").InnerText;
                        rule.Method = nlstRules[i].SelectSingleNode("method").InnerText;

                        RedirectRules.Add(rule);
                    }

                    XmlNode nodeFileSettingCacheExpire = xmlDoc.DocumentElement.SelectSingleNode("//Configuration/RedirectRulesFile");
                    long fileSettingCacheExpire = Lib.Object2Long(nodeFileSettingCacheExpire.Attributes["cacheExpire"].Value);
                    if (fileSettingCacheExpire <= 0)
                    {
                        fileSettingCacheExpire = 3600;// default 1h
                    }

                    CacheDependency fileDependency = new CacheDependency(configFilePath);
                    HttpContext.Current.Cache.Insert(cacheName, RedirectRules, fileDependency, DateTime.Now.AddSeconds(fileSettingCacheExpire), TimeSpan.Zero, CacheItemPriority.Normal, null);
                }
                catch (Exception ex)
                {
                }
            }
        }

        public bool Redirect(string currentUrl)
        {
            bool mustRedirect = false;

            Regex rex;

            for (int i = 0; i < RedirectRules.Count; i++)
            {
                RedirectRule rule = RedirectRules[i];
                rex = new Regex("^" + rule.Url, RegexOptions.IgnoreCase);
                Match match = rex.Match(currentUrl);

                if (match.Success)
                {
                    string parameters = rex.Replace(currentUrl, rule.Parameters);
                    mustRedirect = (bool)this.GetType().InvokeMember(rule.Method, System.Reflection.BindingFlags.InvokeMethod, null, this, new object[] { parameters.Split(',') });
                    break;
                }

            }

            return mustRedirect;
        }
        #endregion

        public static bool Redirect(string[] parameters)
        {
            return RedirectTo(parameters[0]);
        }

        public static bool RedirectToTag(string[] parameters)
        {
            var tag = parameters[0];
            tag = HttpUtility.UrlDecode(tag);
            tag = UnicodeToKoDau(tag);
            tag = Regex.Replace(tag, "[^a-zA-Z0-9]+", "-").Trim();
            if (!string.IsNullOrEmpty(tag))
                return RedirectTo(string.Format("/{0}.html", tag.ToLower()));
            return RedirectTo("/");
        }

        public static bool RedirectToFileNotFoundPage(string suggest = "")
        {
            if (suggest != null && !string.IsNullOrEmpty(suggest))
            {
                suggest = HttpUtility.UrlDecode(Regex.Replace(suggest, "[-_]+", " "));
                return RedirectTo(string.Format("/404.aspx?suggest={0}", suggest));
            }
            return RedirectTo("/404.aspx");
        }


        #region Private methods
        public static bool RedirectTo(string url)
        {
            //var cacheSettings = CacheSettings.GetCurrentSettings();
            //if ((null == cacheSettings || !cacheSettings.EnableCache) ||
            //    (cacheSettings.EnableCache && !CacheController.IsCachedUpdating && !CacheController.IsCachedDeleting))
            //{
            if (!string.IsNullOrEmpty(url))
            {
                try
                {
                    url = string.Format("{0}/{1}", ConfigurationManager.AppSettings["Host"].TrimEnd('/'),
                                        url.TrimStart('/'));
                    HttpContext.Current.Response.CacheControl = "no-cache";
                    HttpContext.Current.Response.RedirectPermanent(url);
                    HttpContext.Current.Response.End();

                    return true;
                }
                catch
                {
                    return false;
                }
            }
            //}

            return false;
        }

        #region Unicode
        public const string uniChars =
            "àáảãạâầấẩẫậăằắẳẵặèéẻẽẹêềếểễệđìíỉĩịòóỏõọôồốổỗộơờớởỡợùúủũụưừứửữựỳýỷỹỵÀÁẢÃẠÂẦẤẨẪẬĂẰẮẲẴẶÈÉẺẼẸÊỀẾỂỄỆĐÌÍỈĨỊÒÓỎÕỌÔỒỐỔỖỘƠỜỚỞỠỢÙÚỦŨỤƯỪỨỬỮỰỲÝỶỸỴÂĂĐÔƠƯ";

        public const string KoDauChars =
            "aaaaaaaaaaaaaaaaaeeeeeeeeeeediiiiiooooooooooooooooouuuuuuuuuuuyyyyyAAAAAAAAAAAAAAAAAEEEEEEEEEEEDIIIOOOOOOOOOOOOOOOOOOOUUUUUUUUUUUYYYYYAADOOU";

        public static string UnicodeToKoDau(string s)
        {
            if (string.IsNullOrEmpty(s))
                return s;
            string retVal = String.Empty;
            int pos;
            for (int i = 0; i < s.Length; i++)
            {
                pos = uniChars.IndexOf(s[i].ToString());
                if (pos >= 0)
                    retVal += KoDauChars[pos];
                else
                    retVal += s[i];
            }
            return retVal;
        }

        public static string UnicodeToKoDauAndGach(string s)
        {
            if (string.IsNullOrEmpty(s))
                return s;
            s = UnicodeToKoDau(s.Trim());
            return Regex.Replace(s, "[^a-zA-Z0-9]+", "-");
        }
        #endregion
        #endregion


    }
}
